#include "../UILib.h"
#include "UIManager.h"
#include <wx/wx.h>
#include <wx/font.h>
#include <wx/dc.h>
#include <wx/stdpaths.h>
#include <wx/filename.h>
#include <wx/dynlib.h>
#include "../Utils/memunzip.h"

BEGIN_NAMESPACE

WXHPEN m_hUpdateRectPen = NULL;
wxApp* CPaintManagerUI::m_pInstance = NULL;
wxApp* CPaintManagerUI::m_pResourceInstance = NULL;
wxString CPaintManagerUI::m_pStrDefaultFontName;//added by cddjr at 05/18/2012
wxString CPaintManagerUI::m_pStrResourcePath;
wxString CPaintManagerUI::m_pStrResourceZip;
bool CPaintManagerUI::m_bCachedResourceZip = false;
CMemUnzip* CPaintManagerUI::m_pResourceZip = NULL;
short CPaintManagerUI::m_H = 180;
short CPaintManagerUI::m_S = 100;
short CPaintManagerUI::m_L = 100;
CStdPtrArray CPaintManagerUI::m_aPreMessages;
CStdPtrArray CPaintManagerUI::m_aPlugins;

CPaintManagerUI::CPaintManagerUI() :
// m_hWndPaint(NULL),
m_pWndPaint(NULL),
// m_hDcPaint(NULL),
m_pDcPaint(NULL),
// m_hDcOffscreen(NULL),
m_pDcOffscreen(NULL),
// m_hDcBackground(NULL),
m_pDcBackground(NULL),
// m_hbmpOffscreen(NULL),
// m_hbmpBackground(NULL),
// m_hwndTooltip(NULL),
m_pWndTooltip(NULL),
m_bShowUpdateRect(false),
m_uTimerID(0x1000),
m_pRoot(NULL),
m_pFocus(NULL),
m_pEventHover(NULL),
m_pEventClick(NULL),
m_pEventKey(NULL),
m_bFirstLayout(true),
m_bFocusNeeded(false),
m_bUpdateNeeded(false),
m_bMouseTracking(false),
m_bMouseCapture(false),
m_bOffscreenPaint(true),
m_bAlphaBackground(false),
m_bUsedVirtualWnd(false),
m_nOpacity(255),
m_pParentResourcePM(NULL)
{
	m_dwDefaultDisabledColor = 0xFFA7A6AA;
	m_dwDefaultFontColor = 0xFF000000;
	m_dwDefaultLinkFontColor = 0xFF0000FF;
	m_dwDefaultLinkHoverFontColor = 0xFFD3215F;
	m_dwDefaultSelectedBkColor = 0xFFBAE4FF;

	m_pDefaultFontInfo = new wxFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
}

CPaintManagerUI::~CPaintManagerUI()
{
	// Delete the control-tree structures
	for( int i = 0; i < m_aDelayedCleanup.GetSize(); i++ ) 
	{
		delete static_cast<CControlUI*>(m_aDelayedCleanup[i]);
	}

	for( int i = 0; i < m_aAsyncNotify.GetSize(); i++ )
	{
		delete static_cast<TNotifyUI*>(m_aAsyncNotify[i]);
	}

	m_mNameHash.Resize(0);
	if(NULL != m_pRoot) delete m_pRoot;
	if(NULL != m_pDefaultFontInfo) delete m_pDefaultFontInfo;
	
	RemoveAllFonts();
	RemoveAllImages();
	RemoveAllDefaultAttributeList();
	RemoveAllOptionGroups();
	RemoveAllTimers();

	// Reset other parts...
	// if( m_hwndTooltip != NULL ) ::DestroyWindow(m_hwndTooltip);
	if(NULL != m_pWndTooltip)
	{
		delete m_pWndTooltip;
	}
	
	if(NULL != m_pDcOffscreen)
	{
		delete m_pDcOffscreen;
	}

	if( NULL != m_pDcBackground ) 
	{
		delete m_pDcBackground;
	}


// 	if( m_hbmpOffscreen != NULL ) ::DeleteObject(m_hbmpOffscreen);
// 	if( m_hbmpBackground != NULL ) ::DeleteObject(m_hbmpBackground);
// 	if( m_hDcPaint != NULL ) ::ReleaseDC(m_hWndPaint, m_hDcPaint);
	if(NULL == m_pDcPaint)
	{
		delete m_pDcPaint;
	}

	m_aPreMessages.Remove(m_aPreMessages.Find(this));
}

void CPaintManagerUI::Init( wxWindow* pWnd )
{
	m_pWndPaint = pWnd;
	m_pDcPaint = new wxClientDC(pWnd);
	m_aPreMessages.Add(this);
}

void CPaintManagerUI::NeedUpdate()
{
	m_bUpdateNeeded = true;
}

void CPaintManagerUI::Invalidate( wxRect& rcItem )
{
	m_pWndPaint->RefreshRect(rcItem, false);
}

wxClientDC* CPaintManagerUI::GetPaintDC() const
{
	return m_pDcPaint;
}

wxWindow* CPaintManagerUI::GetPaintWindow() const
{
	return m_pWndPaint;
}

wxWindow* CPaintManagerUI::GetTooltipWindow() const
{
	return m_pWndTooltip;
}

wxPoint CPaintManagerUI::GetMousePos() const
{
	return m_ptLastMousePos;
}

wxSize CPaintManagerUI::GetClientSize() const
{
	return m_pWndPaint->GetClientRect().GetSize();
}

wxSize CPaintManagerUI::GetInitSize()
{
	return m_szInitWindowSize;
}

void CPaintManagerUI::SetInitSize( int cx, int cy )
{
	m_szInitWindowSize.Set(cx, cy);
	if( NULL != m_pRoot && NULL != m_pWndPaint ) 
	{
		m_pWndPaint->SetSize(m_szInitWindowSize);
	}
}

wxRect& CPaintManagerUI::GetSizeBox()
{
	return m_rcSizeBox;
}

void CPaintManagerUI::SetSizeBox( wxRect& rcSizeBox )
{
	m_rcSizeBox = rcSizeBox;
}

wxRect& CPaintManagerUI::GetCaptionRect()
{
	return m_rcCaption;
}

void CPaintManagerUI::SetCaptionRect( wxRect& rcCaption )
{
	m_rcCaption = rcCaption;
}

wxSize CPaintManagerUI::GetRoundCorner() const
{
	return m_szRoundCorner;
}

void CPaintManagerUI::SetRoundCorner( int cx, int cy )
{
	m_szRoundCorner.Set(cx, cy);
}

wxSize CPaintManagerUI::GetMinInfo() const
{
	return m_szMinWindow;
}

void CPaintManagerUI::SetMinInfo( int cx, int cy )
{
	wxASSERT(cx>=0 && cy>=0);
	m_szMinWindow.Set(cx, cy);
}

wxSize CPaintManagerUI::GetMaxInfo() const
{
	return m_szMaxWindow;
}

void CPaintManagerUI::SetMaxInfo( int cx, int cy )
{
	wxASSERT(cx>=0 && cy>=0);
	m_szMaxWindow.Set(cx, cy);
}

int CPaintManagerUI::GetTransparent() const
{
	return m_nOpacity;
}

void CPaintManagerUI::SetTransparent( int nOpacity )
{
	if (nOpacity<0)
	{
		m_nOpacity = 0;
	}
	else if (nOpacity>255)
	{
		m_nOpacity = 255;
	}
	else
	{
		m_nOpacity = nOpacity;
	}

	m_pWndPaint->SetTransparent(m_nOpacity);
}

void CPaintManagerUI::SetBackgroundTransparent( bool bTrans )
{
	m_bAlphaBackground = bTrans;
}

bool CPaintManagerUI::IsShowUpdateRect() const
{
	return m_bShowUpdateRect;
}

void CPaintManagerUI::SetShowUpdateRect( bool show )
{
	m_bShowUpdateRect = show;
}

wxApp* CPaintManagerUI::GetInstance()
{
	return m_pInstance;
}

wxString CPaintManagerUI::GetInstancePath()
{
	wxString				strAppPath;
	wxStandardPathsBase&	stdp			= wxStandardPaths::Get();
	wxFileName				exeFile(stdp.GetExecutablePath());
	
	strAppPath = exeFile.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);

	if(wxT('\\') != strAppPath.at(strAppPath.Length() - 1)
		&& wxT('/') != strAppPath.at(strAppPath.Length() - 1))
	{
		strAppPath.Append(wxT('/'));
	}

	return strAppPath;
}

wxString CPaintManagerUI::GetCurrentPath()
{
	return GetInstancePath();
}

wxApp* CPaintManagerUI::GetResourceDll()
{
	if(NULL == m_pResourceInstance)
	{
		return m_pInstance;
	}

	return m_pResourceInstance;
}

const wxString& CPaintManagerUI::GetResourcePath()
{
	return m_pStrResourcePath;
}

const wxString& CPaintManagerUI::GetResourceZip()
{
	return m_pStrResourceZip;
}

bool CPaintManagerUI::IsCachedResourceZip()
{
	return m_bCachedResourceZip;
}

CMemUnzip* CPaintManagerUI::GetResourceZipHandle()
{
	return m_pResourceZip;
}

void CPaintManagerUI::SetInstance( wxApp* hInst )
{
	 m_pInstance = hInst;
}

void CPaintManagerUI::SetCurrentPath( WXLPCSTR pStrPath )
{
	
}

void CPaintManagerUI::SetResourceDll( WXHINSTANCE hInst )
{

}

void CPaintManagerUI::SetResourcePath( WXLPCSTR pStrPath )
{

}

void CPaintManagerUI::SetResourceZip( WXLPVOID pVoid, unsigned int len )
{
	if( m_pStrResourceZip == wxT("membuffer") ) 
	{
		return;
	}

	if( m_bCachedResourceZip && NULL != m_pResourceZip ) 
	{
		delete m_pResourceZip;
		m_pResourceZip = NULL;
	}

	m_pStrResourceZip = _T("membuffer");
	m_bCachedResourceZip = true;
	if( m_bCachedResourceZip ) 
	{
		m_pResourceZip = new CMemUnzip;
		m_pResourceZip->LoadMemory((byte *)pVoid, len, true);
	}
}

void CPaintManagerUI::GetHSL( short* H, short* S, short* L )
{
	*H = m_H;
	*S = m_S;
	*L = m_L;
}

void CPaintManagerUI::SetHSL( bool bUseHSL, short H, short S, short L )
{
	if( H == m_H && S == m_S && L == m_L ) 
	{
		return;
	}

	m_H = CLAMP(H, 0, 360);
	m_S = CLAMP(S, 0, 200);
	m_L = CLAMP(L, 0, 200);
	for( int i = 0; i < m_aPreMessages.GetSize(); i++ ) 
	{
		CPaintManagerUI* pManager = static_cast<CPaintManagerUI*>(m_aPreMessages[i]);
		if( pManager != NULL && pManager->GetRoot() != NULL )
		{
			pManager->GetRoot()->Invalidate();
		}
	}
}

void CPaintManagerUI::ReloadSkin()
{
	for( int i = 0; i < m_aPreMessages.GetSize(); i++ ) 
	{
		CPaintManagerUI* pManager = static_cast<CPaintManagerUI*>(m_aPreMessages[i]);
		pManager->ReloadAllImages();
	}
}

bool CPaintManagerUI::LoadPlugin( WXLPCSTR pstrModuleName )
{
	wxDynamicLibrary		lib(pstrModuleName);

	if( !lib.IsLoaded() )
	{
		return false;
	}

	LPCREATECONTROL lpCreateControl = (LPCREATECONTROL)lib.GetSymbol(wxT("CreateControl"));
	if( lpCreateControl != NULL ) 
	{
		lib.Detach();
		if( m_aPlugins.Find(lpCreateControl) >= 0 ) return true;
		m_aPlugins.Add(lpCreateControl);
		return true;
	}

	return false;
}

CStdPtrArray* CPaintManagerUI::GetPlugins()
{
	return &m_aPlugins;
}

bool CPaintManagerUI::UseParentResource( CPaintManagerUI* pm )
{
	if( pm == NULL ) 
	{
		m_pParentResourcePM = NULL;
		return true;
	}

	if( pm == this ) 
	{
		return false;
	}

	CPaintManagerUI* pParentPM = pm->GetParentResource();
	while( pParentPM ) 
	{
		if( pParentPM == this ) 
		{
			return false;
		}

		pParentPM = pParentPM->GetParentResource();
	}

	m_pParentResourcePM = pm;
	return true;
}

CPaintManagerUI* CPaintManagerUI::GetParentResource() const
{
	return m_pParentResourcePM;
}

WXDWORD CPaintManagerUI::GetDefaultDisabledColor() const
{
	if( m_pParentResourcePM ) return m_pParentResourcePM->GetDefaultDisabledColor();
	return m_dwDefaultDisabledColor;
}

void CPaintManagerUI::SetDefaultDisabledColor(WXDWORD dwColor)
{
	m_dwDefaultDisabledColor = dwColor;
}

WXDWORD CPaintManagerUI::GetDefaultFontColor() const
{
	if( m_pParentResourcePM ) return m_pParentResourcePM->GetDefaultFontColor();
	return m_dwDefaultFontColor;
}

void CPaintManagerUI::SetDefaultFontColor(WXDWORD dwColor)
{
	m_dwDefaultFontColor = dwColor;
}

WXDWORD CPaintManagerUI::GetDefaultLinkFontColor() const
{
	if( m_pParentResourcePM ) return m_pParentResourcePM->GetDefaultLinkFontColor();
	return m_dwDefaultLinkFontColor;
}

void CPaintManagerUI::SetDefaultLinkFontColor(WXDWORD dwColor)
{
	m_dwDefaultLinkFontColor = dwColor;
}

WXDWORD CPaintManagerUI::GetDefaultLinkHoverFontColor() const
{
	if( m_pParentResourcePM ) return m_pParentResourcePM->GetDefaultLinkHoverFontColor();
	return m_dwDefaultLinkHoverFontColor;
}

void CPaintManagerUI::SetDefaultLinkHoverFontColor(WXDWORD dwColor)
{
	m_dwDefaultLinkHoverFontColor = dwColor;
}

WXDWORD CPaintManagerUI::GetDefaultSelectedBkColor() const
{
	if( m_pParentResourcePM ) return m_pParentResourcePM->GetDefaultSelectedBkColor();
	return m_dwDefaultSelectedBkColor;
}

void CPaintManagerUI::SetDefaultSelectedBkColor(WXDWORD dwColor)
{
	m_dwDefaultSelectedBkColor = dwColor;
}

wxFont* CPaintManagerUI::GetDefaultFontInfo()
{
	if( m_pParentResourcePM ) return m_pParentResourcePM->GetDefaultFontInfo();

	return m_pDefaultFontInfo;
}

void CPaintManagerUI::SetDefaultFont( WXLPCSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic )
{
	if(NULL != m_pDefaultFontInfo)
	{
		delete m_pDefaultFontInfo;
		m_pDefaultFontInfo = NULL;
	}

	m_pDefaultFontInfo = new wxFont(nSize, 
		wxFONTFAMILY_DEFAULT,
		(FALSE == bItalic)?wxFONTSTYLE_NORMAL:wxFONTSTYLE_ITALIC,
		(FALSE == bBold)?wxFONTWEIGHT_NORMAL:wxFONTWEIGHT_BOLD,
		bUnderline,
		pStrFontName);
}

WXDWORD CPaintManagerUI::GetCustomFontCount() const
{
	return m_aCustomFonts.GetSize();
}

wxFont* CPaintManagerUI::AddFont( WXLPCSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic )
{
	wxFont* pFont = new wxFont(nSize, 
		wxFONTFAMILY_DEFAULT,
		(FALSE == bItalic)?wxFONTSTYLE_NORMAL:wxFONTSTYLE_ITALIC,
		(FALSE == bBold)?wxFONTWEIGHT_NORMAL:wxFONTWEIGHT_BOLD,
		bUnderline,
		pStrFontName);

	if( false == m_aCustomFonts.Add(pFont) )
	{
		delete pFont;
		return NULL;
	}

	return pFont;
}

wxFont* CPaintManagerUI::AddFontAt( int index, WXLPCSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic )
{
	wxFont* pFont = new wxFont(nSize, 
		wxFONTFAMILY_DEFAULT,
		(FALSE == bItalic)?wxFONTSTYLE_NORMAL:wxFONTSTYLE_ITALIC,
		(FALSE == bBold)?wxFONTWEIGHT_NORMAL:wxFONTWEIGHT_BOLD,
		bUnderline,
		pStrFontName);

	if( false == m_aCustomFonts.InsertAt(index, pFont) )
	{
		delete pFont;
		return NULL;
	}

	return pFont;
}

wxFont* CPaintManagerUI::GetFont( int index )
{
	if( index < 0 || index >= m_aCustomFonts.GetSize() ) 
	{
		return GetDefaultFontInfo();
	}

	return static_cast<wxFont*>(m_aCustomFonts[index]);
}

wxFont* CPaintManagerUI::GetFont( WXLPCSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic )
{
	wxFont* pFontInfo = NULL;
	for( int it = 0; it < m_aCustomFonts.GetSize(); it++ ) 
	{
		pFontInfo = static_cast<wxFont*>(m_aCustomFonts[it]);
		if( pFontInfo->GetFaceName() == pStrFontName 
			&& pFontInfo->GetPointSize() == nSize
			&& pFontInfo->GetWeight() == ((FALSE == bBold)?wxFONTWEIGHT_NORMAL:wxFONTWEIGHT_BOLD)
			&& pFontInfo->GetUnderlined() == bUnderline
			&& pFontInfo->GetStyle() == ((FALSE == bItalic)?wxFONTSTYLE_NORMAL:wxFONTSTYLE_ITALIC)) 
		{
			return pFontInfo;
		}
	}

	if( m_pParentResourcePM ) 
	{
		return m_pParentResourcePM->GetFont(pStrFontName, nSize, bBold, bUnderline, bItalic);
	}

	return NULL;
}

bool CPaintManagerUI::FindFont( wxFont* pFont )
{
	wxFont* pFontInfo = NULL;
	for( int it = 0; it < m_aCustomFonts.GetSize(); it++ ) 
	{
		pFontInfo = static_cast<wxFont*>(m_aCustomFonts[it]);
		if( pFontInfo == pFont ) 
		{
			return true;
		}
	}

	if( m_pParentResourcePM ) 
	{
		return m_pParentResourcePM->FindFont(pFont);
	}

	return false;
}


END_NAMESPACE